Skip to content

Conversation

@xingxue-ibm
Copy link
Contributor

On AIX, <sys/stat.h> declares field tv_nsec of struct timespec as long, but the underlying system calls return a 4-byte value in both 32-bit and 64-bit modes. This PR changes to declare tv_nsec as i32 in the libc crate to avoid including the other undefined 4 bytes in the 64-bit mode.

Description

Sources

Checklist

  • Relevant tests in libc-test/semver have been updated
  • No placeholder or unstable values like *LAST or *MAX are
    included (see #3131)
  • Tested locally (cd libc-test && cargo test --target mytarget);
    especially relevant for platforms that may not be checked in CI

@xingxue-ibm
Copy link
Contributor Author

@rustbot label +stable-nominated

@rustbot rustbot added the stable-nominated This PR should be considered for cherry-pick to libc's stable release branch label Oct 17, 2025
@xingxue-ibm xingxue-ibm force-pushed the fix-tv_nsec branch 2 times, most recently from c1d80a2 to ffaf067 Compare October 17, 2025 19:05
src/unix/mod.rs Outdated
Comment on lines 71 to 76
// On AIX, <stat.h> declares 'tv_nsec' as 'long', but the underlying
// system calls return a 4-byte value in both 32-bit and 64-bit modes.
// It is declared as 'i32' to avoid using the other undefined 4 bytes
// in the 64-bit mode.
#[cfg(not(target_env = "gnu"))]
pub struct timespec {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make things a bit cleaner, maybe exclude target_os = "aix" here? Then put the struct in src/unix/aix/mod.rs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed as suggested, thanks!

@tgross35
Copy link
Contributor

tgross35 commented Oct 22, 2025

On AIX, <sys/stat.h> declares field tv_nsec of struct timespec as long, but the underlying system calls return a 4-byte value in both 32-bit and 64-bit modes. This PR changes to declare tv_nsec as i32 in the libc crate to avoid including the other undefined 4 bytes in the 64-bit mode.

I think this is reasonable to change on our side, but isn't it a problem for C users as well if the header doesn't match the syscalls? Technically posix specifies tv_nsec as long too https://pubs.opengroup.org/onlinepubs/009695399/basedefs/time.h.html so I'm surprised the syscalls differ (X32 is a weird exception here)

@xingxue-ibm
Copy link
Contributor Author

xingxue-ibm commented Oct 22, 2025

On AIX, <sys/stat.h> declares field tv_nsec of struct timespec as long, but the underlying system calls return a 4-byte value in both 32-bit and 64-bit modes. This PR changes to declare tv_nsec as i32 in the libc crate to avoid including the other undefined 4 bytes in the 64-bit mode.

I think this is reasonable to change on our side, but isn't it a problem for C users as well if the header doesn't match the syscalls? Technically posix specifies tv_nsec as long too https://pubs.opengroup.org/onlinepubs/009695399/basedefs/time.h.html so I'm surprised the syscalls differ (X32 is a weird exception here)

The problem can be reproduced with a C test case as well. AIX should have mapped stat and its variants to a new set of ABIs that return tv_nsec as a long when compiling for POSIX code, but it appears that this was not done. However, AIX provides something such as the statx system call that accepts two additional arguments, including Command. The caller can specify the STX_TIMESPEC flag to use struct timespec instead of st_timespec. In 64-bit mode, this flag causes statx to treat tv_nsec as an 8-byte value. However, the actual value returned in tv_nsec is still only 4 bytes, with the upper 4 bytes cleared, no additional precision is provided.

Exposing statx and the other stat variants with the x suffix, along with the full set of flags for the Command flag definitions, and implementing Rust’s stat functions on top of them would be quite complex. Moreover, doing so would not provide any real benefit, since no extra precision is gained. On the other hand, the libc crate already contains code to handle a similar situation on x86, where tv_nsec is always 8 bytes in both 32-bit and 64-bit modes. After discussion internally, we thought it would be cleaner to do the same for AIX.

@rustbot
Copy link
Collaborator

rustbot commented Oct 22, 2025

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

Copy link
Contributor

@tgross35 tgross35 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, thanks!

@tgross35 tgross35 added this pull request to the merge queue Oct 22, 2025
Merged via the queue into rust-lang:main with commit 96eb752 Oct 22, 2025
51 of 52 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

O-unix stable-nominated This PR should be considered for cherry-pick to libc's stable release branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants